package cn.simon.free.logtrack.aspect;

import cn.simon.free.logtrack.annotation.LogTrack;
import cn.simon.free.logtrack.core.LogTrackInit;
import cn.simon.free.logtrack.enums.LogTrackEnum;
import cn.simon.free.logtrack.utils.LogTrackUtils;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Maps;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author simon
 * @date 2021/4/17 10:11
 * @copyright:
 * @modifier
 * @motto a no talent, people who have to study hard
 */
@Aspect
@Component
@ConditionalOnBean(LogTrackInit.class)
public class LogTrackAspect {

    private final static ThreadLocal<AtomicInteger> count = new ThreadLocal<>();
    private final Logger log = LoggerFactory.getLogger(getClass());

    @Pointcut("@annotation(cn.simon.free.logtrack.annotation.LogTrack)")
    public void logTrackCut() {
    }

    @Before("logTrackCut()")
    public void before(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        LogTrack annotation = method.getAnnotation(LogTrack.class);
        //如果不为空,就说明有订单追踪日志,就设置默认参数
        if (Objects.nonNull(annotation) && annotation.enable()) {
            AtomicInteger atomicInteger = MoreObjects.firstNonNull(count.get(), new AtomicInteger(0));
            atomicInteger.incrementAndGet();
            count.set(atomicInteger);
            HashMap<String, String> maps = Maps.newHashMap();
            maps.put(LogTrackEnum.LOG_TRACK_MARK.getValue(), UUID.randomUUID().toString());
            maps.put(LogTrackEnum.LOG_TRACK_NAME.getValue(), annotation.name());
            LogTrackUtils.init(maps);
        }
    }

    @AfterReturning("logTrackCut()")
    public void saveLog(JoinPoint joinPoint) {
        if (count.get().decrementAndGet() != 0) {
            return;
        }
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        LogTrack annotation = method.getAnnotation(LogTrack.class);
        if (Objects.nonNull(annotation) && annotation.enable() && annotation.isOut()) {
            LogTrackUtils.get().stream().forEach(str -> log.info("方法:{},链路日志:{}", method.getName(), str));
        }
        try {
            count.remove();
            LogTrackUtils.remove();
        } catch (Exception e) {

        }
    }
}
